#include"graph.h"
#include<fstream>
#include<iostream>
Graph::Graph(int v){    //建立固定顶点的图
    this->_V=v;     //初始化顶点个数
    this->_E=0;     //初始化边为0
}
Graph::Graph(const string& filename){
    //从文件读取V&E，初始化图
    fstream f;
    f.open(filename,ios::in);
    if(!f){
        std::cerr<<"can't open file"<<endl;
        exit(-1);
    }
    int V,E;
    f>>V>>E;
    this->_V=V;
    this->_E=E;
    _adj=new Vertextable[V];  //新建接邻表 
    for(int i=0;i<V;i++){
        _adj[i].data=i;
    }
    for(int i=0;i<E;i++){//将每一个边读入
        int in_vertex,out_vertex;
        f>>in_vertex>>out_vertex;//就按照格式读入
        //开始建立十字链表
        //1、首先从文件建立一个边
        Sidetable *edge=new Sidetable(in_vertex,out_vertex);//初始化一个边
        //2、查找这个边的两边端点，在顶点表中查找并且建立联系
        //查找这条边的起点，同时查找某个点，添加为“出边”
        if(!_adj[in_vertex].firstout){
            //如果某个点的出边为nullptr,就可以将这个点的出边指向刚新建的边上
            _adj[in_vertex].firstout=edge;            
        }else{
            //如果这个点已经有一条出边了，那么就往后遍历，添加到最后一个节点的headlink上
            Sidetable *p=_adj[in_vertex].firstout;
            while(p->headlink){
                p=p->headlink;
            }
            p->headlink=edge;
        }
        //查找这条边的终点，同时查找某个点，添加为“入边”
        if(!_adj[out_vertex].firstin){
            //如果某个点的入边为nullptr,则可以将这点的入边指向刚新建的边上
            _adj[out_vertex].firstin=edge;
        }else{
            //如果这个点已经有一条入边了，那么就往后遍历，添加到最后一个节点的taillink上
            Sidetable *p=_adj[out_vertex].firstin;
            while(p->taillink){
                p=p->taillink;
            }
            p->taillink=edge;
        }
    }
    f.close();//关闭文件
}
int Graph::V() const{return _V;}
int Graph::E() const{return _E;}
Graph::Vertextable Graph::adj(int v){  //获取某个顶点的接邻点
    return _adj[v];
}
Graph::Vertextable* Graph::adj(){  //单独获取接邻表
    return _adj;
}